package {
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
		
	public class Asteroids extends Sprite
	{
		private var player_ship:Ship;
		private var rotational_speed:Number = 0;
		private var velocity_x:Number = 0;
		private var velocity_y:Number = 0;
		private var thrust:Number = 0;		
		private var laser_head:LaserNode;
		private var laser_tail:LaserNode;
		private var asteroids:Array = new Array();
		
		public function Asteroids()
		{
			for(var c:int = 0; c<10; c++)
			{
				var temp_asteroid:Asteroid = new Asteroid( Math.random()*3 );
				temp_asteroid.x = Math.random() * this.stage.stageWidth;
				temp_asteroid.y = Math.random() * this.stage.stageHeight;
				this.addChild(temp_asteroid);
				asteroids.push(temp_asteroid);				
			}
			
			// Initiate LinkedList
			this.laser_head = new LaserNode();
			this.laser_tail = this.laser_head;
			
			// Set stage parameters
			this.stage.scaleMode = StageScaleMode.NO_SCALE;
			this.stage.align = StageAlign.TOP_LEFT;
						
			// Set background to black			
			this.graphics.beginFill(0x000000);
			this.graphics.drawRect(0, 0, this.stage.stageWidth, this.stage.stageHeight);
			
			// Create player ship and center them
			this.player_ship = new Ship();
			this.player_ship.x = this.stage.stageWidth / 2;
			this.player_ship.y = this.stage.stageHeight / 2;
			
			// Add them to the display
			this.addChild(this.player_ship);
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			this.stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);			
			this.addEventListener(Event.ENTER_FRAME, onEnterFrame);

		}
		
		public function onEnterFrame(e:Event):void
		{
			// Adjust the base rotation
			this.player_ship.rotation += this.rotational_speed;			
			
			// Increase the velocity by adding the component vectors
			this.velocity_x += Math.cos(this.player_ship.rotation * Math.PI / 180) * this.thrust;
			this.velocity_y += Math.sin(this.player_ship.rotation * Math.PI / 180) * this.thrust;
			
			// Apply "friction"
			this.velocity_x *= Math.abs(this.velocity_x)<0.01? 0 : 0.97;
			this.velocity_y *= Math.abs(this.velocity_y)<0.01? 0 : 0.97;			
		
			// Update the position
			this.player_ship.x += this.velocity_x;
			this.player_ship.y += this.velocity_y;
		
			// Reposition if the ship has moved off-stage
			if (this.player_ship.x >= this.stage.stageWidth)
			{
				this.player_ship.x = 0;
			}
			else if (this.player_ship.x <= 0)
			{
				this.player_ship.x = this.stage.stageWidth;
			}
			
			if (this.player_ship.y >= this.stage.stageHeight)
			{
				this.player_ship.y = 0;
			}
			else if (this.player_ship.y <= 0)
			{
				this.player_ship.y = this.stage.stageHeight;
			}	
						
			// Update the position of lasers
			var current_node:LaserNode = this.laser_head;

			while( current_node.next )
			{
				if ( current_node.next.laser.off_stage() )
				{
					// Delete this laser object
					this.removeChild(current_node.next.laser);
					current_node.next.laser = null;					
					
					// Reset tail if we deleted it
					if ( this.laser_tail == current_node.next )
					{
						this.laser_tail = current_node;
					}
					
					// Update the linked list to remove the dead node
					current_node.next = current_node.next.next;
					
					continue;
				}
				
				// Iterate to next node	
				current_node = current_node.next;
				current_node.laser.update_position();
				
				for(var i:int = 0; i < asteroids.length; i++)
				{
					 
					if ( asteroids[i].visible && this.asteroids[i].hitTestPoint( current_node.laser.x, current_node.laser.y) )
					{
						asteroids[i].visible = false;
					}
				}
	
			}
			
	
		}
		
		public function onKeyUp(e:KeyboardEvent):void
		{
			switch (e.keyCode)
			{
				// Clear rotational speeds
				case Keyboard.LEFT:
				case Keyboard.RIGHT:					
					this.rotational_speed = 0;
				break;
				
				// Release thrust
				case Keyboard.UP:
					this.thrust = 0;
					this.player_ship.flameOff();
				break;
			}
		}
		
		public function onKeyDown(e:KeyboardEvent):void
		{			
			switch (e.keyCode)
			{
				// Reset Everything
				case Keyboard.DELETE:
					this.player_ship.x = this.stage.stageWidth / 2;
					this.player_ship.y = this.stage.stageHeight / 2;
					this.player_ship.rotation = 0;
					this.thrust = 0;
					this.velocity_x = 0;
					this.velocity_y = 0;
					
					var current_node:LaserNode = this.laser_head;
					while( current_node.next )
					{
						if ( current_node.next.laser )
						{
							this.removeChild(current_node.next.laser);
							current_node.next.laser = null;
						}
						current_node.next = current_node.next.next;
					}
					this.laser_tail = this.laser_head;
				break;
				
				// Give a negative (counter-clockwise) rotational speed
				case Keyboard.LEFT :
					this.rotational_speed = -15;
				break;
				
				// Give a positive (clockwise) rotational speed
				case Keyboard.RIGHT :
					this.rotational_speed = 15;
				break;
				
				case Keyboard.UP:
					this.thrust = 0.4;
					this.player_ship.flameOn();
				break;
				
				case Keyboard.SPACE:				
					// Add a new node after at the end
					this.laser_tail.next = new LaserNode( new Laser(this.player_ship.rotation, this.player_ship.x, this.player_ship.y) );
					
					// Make the tail point to the new tail node
					this.laser_tail = this.laser_tail.next;
					
					// Add bullet to display list
					this.addChild(this.laser_tail.laser);					
				break;		
			}				
		}
	}

}